Namespace ShapeLibrary.Design
    ''' 
    '''		We have a custom serializer that can dynamically create
    '''		WindowsFormsAdapter objects for shape containers based on
    '''		the value of the design time "Control" property on the 
    '''		container.  Code serialization works by writing whatever
    '''		you want during serialize.  During deserialization each
    '''		serializer will receive a statement collection consisting
    '''		of statements that are associated with the type the
    '''		serializer is deserializing.  In our adapter example,
    '''		The ShapeContainer serializer creates local variables
    '''		of type WindowsFormsAdapter.  But during deserialization,
    '''		all statements associated with WindowsFormsAdapter do not
    '''		go back to the ShapeContainer's serialzer -- it will only get
    '''		code statements associated with shape containers!  Where
    '''		will the statements for WindowsFormsAdapter go?  They will
    '''		go here, and it is up to us to do something with them.  What
    '''		we do with them is simple:  We extract the control parameter
    '''		of the Connect method and set this value into the Control
    '''		property on the shape.
    ''' 
    Friend Class WindowsFormsAdapterCodeDomSerializer
        Inherits CodeDomSerializer
        ''' 
        ''' We implement this for the abstract method on CodeDomSerializer.
        ''' The provided codeObject contains a collection of statements.  The
        ''' target object of each statement points to something that is a
        ''' WindowsFormsAdapter object.  The key part of all of this code is
        ''' a call to the Connect method on the object.  We search for that,
        ''' and pull out the arguments it takes.  
        ''' 
        Public Overrides Function Deserialize(ByVal manager As IDesignerSerializationManager, ByVal codeObject As Object) As Object
            If TypeOf codeObject Is CodeStatementCollection Then
                Dim statements As CodeStatementCollection = CType(codeObject, CodeStatementCollection)
                ' Search for this line of code:
                '
                '		myShapeAdapter.Connect(someControl, someShapeContainer);
                '
                ' We want to find the name of someControl and someShapeContainer.  From the
                ' name we can ask the designer serialization manager for instances of those
                ' objects, and then we can finally hook the two together at design time to
                ' make the shape container paint on the correct control.
                Dim statement As CodeStatement
                For Each statement In statements
                    If TypeOf statement Is CodeExpressionStatement Then
                        Dim expression As CodeExpression = CType(statement, CodeExpressionStatement).Expression
                        If TypeOf expression Is CodeMethodInvokeExpression Then
                            Dim method As CodeMethodInvokeExpression = CType(expression, CodeMethodInvokeExpression)
                            If method.Method.MethodName.Equals("Connect") Then
                                ' This is our method.  We need both parameters.
                                '
                                Dim controlParam As CodeExpression = method.Parameters(0)
                                Dim shapeContainerParam As CodeExpression = method.Parameters(1)

                                Dim controlObject As Object = DeserializeExpression(manager, Nothing, controlParam)
                                Dim shape As Object = DeserializeExpression(manager, Nothing, shapeContainerParam)
                                If Not (shape Is Nothing) AndAlso TypeOf controlObject Is Control Then
                                    Dim control As Control = CType(controlObject, Control)
                                    Dim prop As PropertyDescriptor = TypeDescriptor.GetProperties(shape)("Control")
                                    If Not (prop Is Nothing) AndAlso prop.PropertyType Is GetType(Control) Then
                                        prop.SetValue(shape, control)
                                        Exit For
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next statement
            End If

            ' We never create a instance of this object.
            '
            Return Nothing
        End Function

        '''
        '''     Serializes the given object into a CodeDom object.  We don't do anything here, because
        '''     we never create an instance of this object at design time.
        '''
        Public Overrides Function Serialize(ByVal manager As IDesignerSerializationManager, ByVal value As Object) As Object
            ' We are never invoked to serialize.
            Return Nothing
        End Function
    End Class
End Namespace
